﻿using Grow.Db.Repository;
using Grow.Db.UnitOfWork;
using Grow.EventBus.Cap.Enum;
using Grow.EventBus.Cap.Job;
using Grow.EventBus.Cap.SubscriberEventData;
using Grow.EventBus.Cap.SubscriberHandler;
using Grow.Module.Service;
using Grow.Scheduler;

namespace Grow.EventBus.Cap.MessageListener
{
    public class MessageListener : IMessageListener
    {
        private readonly IServiceContext _serviceContext;
        private readonly ISubscriberHandler _subscriberHandler;
        private readonly IScheduler _scheduler;
        public MessageListener(IServiceContext serviceContext)
        {
            _serviceContext = serviceContext;
            _subscriberHandler = _serviceContext.GetRequiredService<ISubscriberHandler>();
            _scheduler = _serviceContext.GetRequiredService<IScheduler>();
        }


        public async Task<bool> ExecuteAsync(SubscriberEventDataDto subscriberEventDataDto, CancellationToken cancellationToken = default)
        {
            try
            {
                await SaveSubscriberEventDataAsync(subscriberEventDataDto, cancellationToken);
                // 非延迟事件直接进入执行队列
                if (!subscriberEventDataDto.DelayAt.HasValue || subscriberEventDataDto.DelayAt.Value <= DateTimeOffset.Now)
                {
                    await _subscriberHandler.ExecuteAsync(subscriberEventDataDto, cancellationToken);
                }
                else
                {
                    _scheduler.AddSchedule<DelaySubscriberJob, SubscriberEventDataDto>(subscriberEventDataDto, subscriberEventDataDto.DelayAt.Value, cancellationToken);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        private async Task SaveSubscriberEventDataAsync(SubscriberEventDataDto subscriberEventDataDto, CancellationToken cancellationToken = default)
        {
            var serviceContext = _serviceContext.GetServiceContext();
            var eventBusOptions = serviceContext.GetOptions<EventBusOptions>();
            var unitOfWorkManager = serviceContext.GetRequiredService<IUnitOfWorkManager>();
            var subscriberEventDataRepository = serviceContext.GetRequiredService<IRepository<SubscriberEventDataEntity>>();

            SubscriberEventDataEntity subscriberEventDataEntity = new(
               subscriberEventDataDto.EventDataId,
               eventBusOptions.EnvironmentName,
               subscriberEventDataDto.EventName,
               subscriberEventDataDto.EventHandlerName,
               subscriberEventDataDto.EventDataType,
               subscriberEventDataDto.EventHandlerType,
               subscriberEventDataDto.EventBody,
               subscriberEventDataDto.EventHeads,
               EventDataStatusEnum.Wait,
               0,
               subscriberEventDataDto.SendAt,
               subscriberEventDataDto.DelayAt,
               null,
               null);

            await subscriberEventDataRepository.AddAsync(subscriberEventDataEntity, cancellationToken);
            await unitOfWorkManager.CommitAsync(cancellationToken);
        }
    }
}
